import ModuleLoader from "../ModuleLoader";

import * as Express from 'express'

import { _Application } from '../Application'
import Method from "../utils/Method";

import { parse } from 'querystring'

var bodyParser = require('body-parser');
var multer = require('multer');

var fs = require('fs');
var path = require('path')

import * as _ from 'lodash';


function createDefWebServer() {
    var __webServer = new Express();

    var options = {
        dotfiles: 'ignore',
        etag: false,
        extensions: ['htm', 'html', 'png', 'gif', 'jpg'],
        index: false,
        maxAge: '1d',
        redirect: true,
        setHeaders: function (res, path, stat) {
            res.set('x-timestamp', Date.now())
        }
    }

    __webServer.use(Express.static('public', options))

    __webServer.use(bodyParser.urlencoded({ extended: false }));
    __webServer.use(multer({ dest: '/tmp/' }).array('file'));

    __webServer.use(function (req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "*");
        res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
        res.header("X-Powered-By", ' 3.2.1')
        res.header("Content-Type", "application/json;charset=utf-8");
        next();
    });

    return __webServer;
}



export default class WebServer {
    private _ModuleLoader: ModuleLoader;
    private _WebServer: Express;
    private _Port: number;
    private _Options: any;
    constructor(moduleLoader: ModuleLoader, webServer: any, httpconfig: any) {

        this._ModuleLoader = moduleLoader;
        this._WebServer = webServer || createDefWebServer();
        this._Options = _.cloneDeep(httpconfig);
        this._Port = this._Options.port;
    }

    private init() {
        let callMethod = function (method: Function, session, msg, res) {
            method(session, msg).then(function (response) {
                res.send(response);
            }).catch(function (err) {
                res.status(500);
                res.json({
                    code: 500,
                    message: err.message,
                });
            })
        }
        let excuteMethod = function (req, res, route) {
            //TODO 处理授权
            let xmethod = req.method;
            let path = req.path;
            let authorization = req.headers['X-Authorization'];
            //设置path 以及 用户信息,IP,
            let session = { path: path };

            //解析路径参数
            let msg = req.query || {};

            let urlParams = route.params || [];

            if (urlParams.length > 0) {
                let segs = path.substring(1).split('/');
                for (let i = 0; i < urlParams.length; i++) {
                    let urlParam = urlParams[i];
                    let iIndex = Number(urlParam.index);
                    let pathVal = segs[iIndex];
                    if (pathVal) {
                        msg[urlParam.key] = pathVal;
                    }
                }
            }

            if (route.method && route.module) {
                if (xmethod == Method.POST) {
                    let data = '';
                    req.on('data', function (chunk) {
                        data += chunk;
                    });
                    req.on('end', function () {
                        try {
                            let body = JSON.parse(data);
                            Object.assign(msg, body);
                        } catch (e) {
                            try {
                                let _b = parse(data);
                                Object.assign(msg, _b);
                            } catch (e) { }
                        }

                        callMethod(route.module[route.method].bind(route.module), session, msg, res);
                    })
                } else {

                    callMethod(route.module[route.method].bind(route.module), session, msg, res);
                }
            } else {
                res.status(404);
                res.json({
                    code: 404,
                    message: 'Module Not Found',
                });
            }
        }

        let self = this;
        //加载模块 
        this._ModuleLoader.loadController(function (err, resp: { code, routeList }) {

            //controller加载成功
            if (!err && resp.code == 200) {

                //设置get请求
                let getList = _Application.getRequestMap().getGetList();
                if (getList) {
                    for (let i = 0; i < getList.length; i++) {
                        let route = getList[i];
                        self._WebServer.get('/' + route.path, function (req, res) {
                            excuteMethod(req, res, route);
                        })
                    }
                }

                //设置post请求
                let postList = _Application.getRequestMap().getPostList();
                if (postList) {
                    for (let i = 0; i < postList.length; i++) {
                        let route = postList[i];
                        self._WebServer.post('/' + route.path, function (req, res) {
                            excuteMethod(req, res, route);
                        })
                    }
                }

                self._WebServer.get('/', function (req, res) {
                    res.redirect('index.html')
                });

                //文件上传接口，通用
                self._WebServer.post('/file_upload', function (req, res) {
                    console.log(req.files[0]);  // 上传的文件信息 
                    let response = { code: 500, message: '', fileName: '', fileDir: '' };
                    let destDir = self._Options.uploadFileDir || __dirname;
                    let originalname = req.files[0].originalname;
                    let filename = req.files[0].filename; 
                    fs.readFile(req.files[0].path, function (err, data) {
                        if (!!err) {
                            response.message = err.message;
                            res.status(500);
                            res.send(response)
                            return;
                        }
                        let dir =  path.resolve(destDir, filename);
                        if (!fs.existsSync(dir)) {
                            fs.mkdirSync(dir);
                        }
                        var des_file = path.resolve(dir, originalname);
                        fs.writeFile(des_file, data, function (err) {
                            if (!!err) {
                                response.message = err.message;
                                res.status(500);
                                res.send(response);
                            } else {
                                response = {
                                    code: 200,
                                    message: 'File uploaded successfully',
                                    fileName: filename + "/" + originalname,
                                    fileDir: destDir
                                };
                                res.send(response);
                            }

                        });
                    });
                })


                self._WebServer.all('*', function (req, res, next) {
                    if (req.method != 'OPTIONS') {
                        res.status(404);
                        res.json({
                            code: 404,
                            message: 'Not Found Request Url',
                        });
                    }
                    next();
                });

                self._WebServer.listen(self._Port, function (_server) {
                    console.log("http server startup on "+self._Port)
                });
            }
        })
    }

    start() {
        this.init();
    }

    stop() {

    }
}